package com.hnichr.ump.oauth.anthentication;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hnichr.ump.oauth.service.OAuth2Service;
import com.hnichr.ump.oauth.service.UserDeptService;
import com.hnichr.ump.oauth.vo.AccessTokenVo;
import com.hnichr.ump.oauth.vo.UserInfoVo;
import com.mxpioframework.common.util.SpringUtil;
import com.mxpioframework.security.anthentication.JwtLoginToken;
import com.mxpioframework.security.entity.User;
import com.mxpioframework.security.entity.UserDept;
import com.mxpioframework.security.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * 用户角色校验具体实现
 */
@Component
public class OauthAuthenticationProvider implements AuthenticationProvider {
    @Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private PasswordEncoder passwordEncoder;

	/** 启用统一认证 */
	@Value("${sso.enabled:false}")
	private boolean enableSSOLogin;

	@Autowired
	private UserService userService;


	/**
	 * 鉴权具体逻辑
	 *
	 * @param authentication
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {

		//首先判断是否外部用户
		 boolean outerUser = false;
		 User u = userService.findByName(authentication.getName());
		 if(u!=null && StringUtils.equals("1",u.getOuterUser())){
			 outerUser = true;
		 }
		UserDetails userDetails = null;
		JwtLoginToken jwtLoginToken = (JwtLoginToken) authentication;

		//非外部用户才能使用sso
		if (!outerUser && enableSSOLogin) {
			// 开启统一认证前提下，name为认证码
			String code = authentication.getName();
			OAuth2Service oAuth2Service = SpringUtil.getBean(OAuth2Service.class);
			// 根据认证码获取到accesstoken
			AccessTokenVo accessTokenVo = oAuth2Service.getAccessToken(code);
			// 根据accesstoken获取用户信息
			UserInfoVo userInfoVo = oAuth2Service.getUserInfo(accessTokenVo.getAccess_token());
			// 先判断用户表里是否有该用户
			UserService userService = SpringUtil.getBean(UserService.class);
			String userId = userInfoVo.getWorkno();
			if (StrUtil.isBlank(userId)) {
				userId = userInfoVo.getAccount();
			}
			User user = userService.findByName(userId);
			if (ObjectUtil.isNull(user)) {
				// 没有用户需要创建
				user = new User();
				user.setUsername(userId);
				user.setNickname(userInfoVo.getRealname());
				/*user.setGender(userInfoVo.getSex());
				user.setPhone(userInfoVo.getPhone());*/
				user.setAdministrator(false);
				userService.create(user);

				// 创建用户与部门关系
				UserDept userDept = null;
				UserDeptService userDeptService = SpringUtil.getBean(UserDeptService.class);
				for (String deptid : userInfoVo.getOrgIds()) {
					userDept = new UserDept();
					userDept.setDeptId(deptid);
					userDept.setUserId(user.getUsername());
					userDeptService.save(userDept);
				}
			}
			userDetails = userDetailsService.loadUserByUsername(userId);
		} else {
			userDetails = userDetailsService.loadUserByUsername(authentication.getName());
			defaultCheck(userDetails);
			// 用户名密码校验 具体逻辑
			additionalAuthenticationChecks(userDetails, jwtLoginToken);
		}
		// 构造已认证的authentication
		JwtLoginToken authenticatedToken = new JwtLoginToken(userDetails, jwtLoginToken.getCredentials(),
				userDetails.getAuthorities());
		return authenticatedToken;
	}

	/**
	 * 是否支持当前类
	 *
	 * @param authentication
	 * @return
	 */
	public boolean supports(Class<?> authentication) {
		return (JwtLoginToken.class.isAssignableFrom(authentication));
	}

	/**
	 * 一些默认信息的检查
	 *
	 * @param user
	 */
	private void defaultCheck(UserDetails user) {
		if (!user.isAccountNonLocked()) {
			throw new LockedException("User account is locked");
		}

		if (!user.isEnabled()) {
			throw new DisabledException("User is disabled");
		}

		if (!user.isAccountNonExpired()) {
			throw new AccountExpiredException("User account has expired");
		}
	}

	/**
	 * 检查密码是否正确
	 *
	 * @param userDetails
	 * @param authentication
	 * @throws AuthenticationException
	 */
	private void additionalAuthenticationChecks(UserDetails userDetails, JwtLoginToken authentication)
			throws AuthenticationException {
		if (authentication.getCredentials() == null) {
			throw new BadCredentialsException("Bad credentials");
		}
		String presentedPassword = authentication.getCredentials().toString();
		if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
			throw new BadCredentialsException("Bad credentials");
		}
	}

}
